// pages/device/device.js
const app = getApp()
const { ModbusRTU, arrayBufferToArray, ByteUtil, ModbusError, ModbusErrorType } = require('../../utils/modbus')
const readNumberOfPoints = 40

Page({
  // 声明一个常量
  SERVICE_ID:'55535343-fe7d-4ae5-8fa9-9fafd205e455',
  READ_CHARACTERISTIC_ID:'49535343-8841-43f4-a8d4-ecbe34729bb3',
  NOTIFY_CHARACTERISTIC_ID:'49535343-1e4d-4bd9-ba61-23c647249616',
  /**
   * 页面的初始数据
   */
  data: {
    deviceName: '',
    deviceId: '',
    isConnected: false,
    temperature: '--',
    humidity: '--',
    light: '--',
    logMessages: [],
    isCollecting: false,
    serviceId: '',
    characteristicId: '',
    notifyId: '',
    // 设备数据对象，用于存储解析后的数据
    deviceData: {
      equiNo: 0, // 设备序列号
      softVersion: 0, // 软件版本
      errorNo: 0, // 错误号
      kdValue: 0, // 开度百分比
      jsylValue: 0, // 进水压力值
      hsylValue: 0, // 回水压力值
      jswdValue: 0, // 进水温度值
      hswdValue: 0, // 回水温度值
      zdqs: 0, // 转圈数
      dqjdcgq: 0, // 单圈角度传感器
      motorCurrent: 0 // 电机电流 (mA)
    }
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad() {
    // 页面加载时清空数据
    // this.clearPageData()
    console.log('页面加载');
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady() {
    console.log('页面初次渲染完成');
  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow() {
    console.log('页面显示');
    
    // 检查设备连接状态
    if (!app.globalData.connectedDevice) {
      wx.switchTab({
        url: '/pages/index/index'
      });
      wx.showToast({
        title: '请先连接设备',
        icon: 'none'
      });
      return;
    }
    
    // 设置tabBar选中状态
    if (typeof this.getTabBar === 'function' && this.getTabBar()) {
      this.getTabBar().setData({
        selected: 1
      });
    }
    
    // 每次进入页面时清空数据
    this.clearPageData()
    
    if (app.globalData.connectedDevice) {
      this.setData({
        deviceId: app.globalData.connectedDevice.deviceId,
        deviceName: app.globalData.connectedDevice.name || '未知设备'
      })

      if(app.globalData.isConnected === true) {
        this.onBLECharacteristicValueChange()
      }
      else{
        this.connectDevice()
      }
    }
  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide() {
    console.log('页面隐藏');
  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload() {
    console.log('页面卸载');
    // 页面卸载时，如果还连接着设备，则断开连接
    if (this.data.isConnected && app.globalData.connectedDevice) {
      wx.closeBLEConnection({
        deviceId: app.globalData.connectedDevice.deviceId,
        success: (res) => {
          console.log('页面卸载时断开连接成功')
          this.cleanupConnection()
        },
        fail: (res) => {
          console.log('页面卸载时断开连接失败，但清理连接资源', res)
          // 即使断开连接失败，也要清理连接资源
          this.cleanupConnection()
        }
      })
    }
  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh() {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom() {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage() {

  },

  connectDevice() {
    const device = app.globalData.connectedDevice
    if(app.globalData.isConnected) {
      return
    }
    
    this.setData({
      deviceId: device.deviceId
    })
    wx.showLoading({
      title: '连接中...'
    })

    wx.createBLEConnection({
      deviceId: device.deviceId,
      success: (res) => {
        this.setData({
          connectedDevice: device,
          isConnected: true
        })
        app.globalData.isConnected = true
        this.getBLEDeviceServices(device.deviceId)
        wx.hideLoading()
        console.log('连接成功')
        this.addLog('设备连接成功')
      },
      fail: (res) => {
        wx.showToast({
          title: '连接失败',
          icon: 'none'
        })
        wx.hideLoading()
        this.addLog('设备连接失败')
        wx.switchTab({
          url: '/pages/index/index',
        })
      }
    })
  },

  getBLEDeviceServices(deviceId) {
    wx.getBLEDeviceServices({
      deviceId,
      success: (res) => {
        const service = res.services.find(s => s.uuid.toLowerCase().includes(this.SERVICE_ID))
        if (service) {
          console.log('找到服务,' + service.uuid)
          this.setData({ serviceId: service.uuid })
          app.globalData.serviceId = service.uuid
          this.getBLEDeviceCharacteristics(deviceId, service.uuid)
        }
      }
    })
  },

  getBLEDeviceCharacteristics(deviceId, serviceId) {
    wx.getBLEDeviceCharacteristics({
      deviceId,
      serviceId,
      success: (res) => {
        const characteristic_read = res.characteristics.find(c => c.uuid.toLowerCase().includes(this.READ_CHARACTERISTIC_ID))
        if (characteristic_read) {
          console.log('找到读数据特征,' + characteristic_read.uuid)
          this.setData({ characteristicId: characteristic_read.uuid })
          app.globalData.characteristicId = characteristic_read.uuid

          let characteristic_notify = res.characteristics.find(c => c.uuid.toLowerCase().includes(this.NOTIFY_CHARACTERISTIC_ID))
          if (characteristic_notify){
            console.log('找到通知特征,' + characteristic_notify.uuid)
            this.setData({ notifyId: characteristic_notify.uuid })
            app.globalData.notifyId = characteristic_notify.uuid
            this.notifyBLECharacteristicValueChange(deviceId, serviceId, characteristic_notify.uuid)
          }
        }
      }
    })
  },

  notifyBLECharacteristicValueChange(deviceId, serviceId, characteristicId) {
    console.log('注册通知 deviceId' + deviceId + ",serviceId:" + serviceId + ",characteristicId:" + characteristicId);
    wx.notifyBLECharacteristicValueChange({
      deviceId,
      serviceId,
      characteristicId,
      state: true,
      success: (res) => {
        console.log('通知开启成功');
        this.onBLECharacteristicValueChange()
      }
    })
  },

  onBLECharacteristicValueChange() {
    //先移除监听
    wx.offBLECharacteristicValueChange()
    
    wx.onBLECharacteristicValueChange((res) => {
      const value = res.value
      // 处理接收到的数据
      console.log('收到数据:', value)
      // 解析数据
      try {
        const resultParsed = this.parseDeviceDataResponse(value, readNumberOfPoints)
        console.log('解析结果:', resultParsed)
        
        // 更新设备数据到界面
        this.setData({
          deviceData: {
            equiNo: resultParsed.equiNo || 0,
            softVersion: resultParsed.softVersion || 0,
            errorNo: resultParsed.errorNo || 0,
            kdValue: resultParsed.kdValue || 0,
            jsylValue: resultParsed.jsylValue || 0,
            hsylValue: resultParsed.hsylValue || 0,
            jswdValue: resultParsed.jswdValue || 0,
            hswdValue: resultParsed.hswdValue || 0,
            zdqs: resultParsed.zdqs || 0,
            dqjdcgq: resultParsed.dqjdcgq || 0,
            motorCurrent: resultParsed.motorCurrentValue || 0
          }
        })
        // 添加日志
        this.addLog(`读取数据成功!`)
        wx.showToast({
          title: '读取数据成功!',
          icon: 'success'
        });

      } catch (error) {
        console.error('数据解析失败:', error)
        this.addLog(`数据解析失败: ${error.message}`)
      }
    })

    setTimeout(() => {
      //发送获取数据请求
      this.onReadDataClick()
    }, 1000)
  },

  disconnectDevice() {
    if (!app.globalData.connectedDevice) {
      wx.showToast({
        title: '未连接设备',
        icon: 'none'
      })

      wx.switchTab({
        url: '/pages/index/index'
      })
      return
    }

    wx.showLoading({
      title: '断开连接中...'
    })

    // 先尝试断开连接
    wx.closeBLEConnection({
      deviceId: app.globalData.connectedDevice.deviceId,
      success: (res) => {
        console.log('断开连接成功:', res)
        this.cleanupConnection()
        this.addLog('设备已断开连接')
        wx.hideLoading()
        wx.showToast({
          title: '已断开连接',
          icon: 'success',
          duration: 1500
        })
        
        // 延迟跳转，让用户看到成功提示
        setTimeout(() => {
          wx.switchTab({
            url: '/pages/index/index'
          })
        }, 1500)
      },
      fail: (res) => {
        console.error('断开连接命令失败:', res)
        // 即使断开连接命令失败，也要清理连接资源
        this.cleanupConnection()
        this.addLog('断开连接命令失败，但已清理连接资源')
        wx.hideLoading()
        wx.showToast({
          title: '连接已清理',
          icon: 'success',
          duration: 1500
        })
        
        // 延迟跳转，让用户看到成功提示
        setTimeout(() => {
          wx.switchTab({
            url: '/pages/index/index'
          })
        }, 1500)
      }
    })
  },

  // 清理连接资源的统一方法
  cleanupConnection() {
    // 清空页面数据
    this.clearPageData()
    // 清除全局数据
    app.globalData.connectedDevice = null
    app.globalData.serviceId = ''
    app.globalData.characteristicId = ''
    app.globalData.notifyId = ''
    app.globalData.isConnected = false
    
    // 移除蓝牙特征值变化监听
    wx.offBLECharacteristicValueChange()
    
    console.log('连接资源已清理')
  },

  onReadDataClick(){
    // 检查是否有已连接设备
    if (!app.globalData.connectedDevice) {
      wx.showToast({
        title: '未连接设备',
        icon: 'none'
      })
      wx.switchTab({
        url: '/pages/index/index'
      })
      return
    }
    
    const frame = ModbusRTU.readInputRegisters(1, 0, readNumberOfPoints)
    console.log('发送帧:', frame)
    this.addLog('发送读取数据指令')
    
    // 发送数据
    wx.writeBLECharacteristicValue({
      deviceId: app.globalData.connectedDevice.deviceId,
      serviceId: app.globalData.serviceId,
      characteristicId: app.globalData.characteristicId,
      value: frame.buffer,
      success: (res) => {
        console.log('发送成功', frame.buffer, res)
        this.addLog('读取数据指令发送成功')
      },
      fail: (res) => {
        console.log('发送失败', res)
        this.addLog('读取数据指令发送失败')
        wx.showToast({
          title: '发送失败',
          icon: 'none'
        })
      }
    })
  },

  addLog(message) {
    const logMessages = this.data.logMessages
    logMessages.unshift({
      time: new Date().toLocaleTimeString(),
      message: message
    })
    if (logMessages.length > 50) {
      logMessages.pop()
    }
    this.setData({ logMessages })
  },

  clearPageData() {
    // 重置所有页面数据到初始状态
    this.setData({
      // 重置设备数据
      deviceData: {
        equiNo: 0,
        softVersion: 0,
        errorNo: 0,
        kdValue: 0,
        jsylValue: 0,
        hsylValue: 0,
        jswdValue: 0,
        hswdValue: 0,
        zdqs: 0,
        dqjdcgq: 0,
        motorCurrent: 0
      }
    })
    
    console.log('页面数据已清空')
  },

  // 手动清空数据（可用于调试或特殊需求）
  manualClearData() {
    this.clearPageData()
    this.addLog('手动清空数据')
    wx.showToast({
      title: '数据已清空',
      icon: 'success'
    })
  },
  
  // 解析设备数据响应
  parseDeviceDataResponse(response, readNumberOfPoints = 40) {
    if (!response || response.byteLength < 3) {
      throw new ModbusError(ModbusErrorType.ModbusResponseError, '响应数据长度不足')
    }

    // 检查数据长度是否符合预期
    const expectedLength = readNumberOfPoints * 2 + 5
    if (response.byteLength !== expectedLength) {
      // throw new ModbusError(ModbusErrorType.ModbusResponseError, `数据长度不匹配，期望${expectedLength}字节，实际${response.byteLength}字节`)
    }

    // 跳过前3个字节（从站地址、功能码、字节数），从第4个字节开始解析数据
    const dataBytes = response.slice(3, response.byteLength - 2) // 去掉CRC校验
    //其中dataBytes类型是ArrayBuffer，将其转为Array数组
    const dataArray = arrayBufferToArray(dataBytes)
    // 解析各个数据项
    const deviceData = {
      kd: ByteUtil.parseInt16FromArray(dataArray, 0), // 开度
      jsylDL: ByteUtil.parseInt16FromArray(dataArray, 1), // 进水压力（电流）
      hsylDL: ByteUtil.parseInt16FromArray(dataArray, 2), // 回水压力（电流）
      jsyl: ByteUtil.parseInt16FromArray(dataArray, 3), // 进水压力1
      hsyl: ByteUtil.parseInt16FromArray(dataArray, 4), // 回水压力1
      jswdDZ: ByteUtil.parseInt16FromArray(dataArray, 5), // 进水温度(电阻)
      hswdDZ: ByteUtil.parseInt16FromArray(dataArray, 6), // 回水温度(电阻)
      hswd: ByteUtil.parseInt16FromArray(dataArray, 7), // 回水温度
      jswd: ByteUtil.parseInt16FromArray(dataArray, 8), // 进水温度
      reserve1: ByteUtil.parseInt16FromArray(dataArray, 9), // 保留
      reserve2: ByteUtil.parseInt16FromArray(dataArray, 10), // 保留
      reserve3: ByteUtil.parseInt16FromArray(dataArray, 11), // 保留
      motorCurrent: ByteUtil.parseInt16FromArray(dataArray, 12), // 电机电流 (mA)
      errorNo: ByteUtil.parseUint16FromArray(dataArray, 13), // 错误号
      alarmState: ByteUtil.parseUint16FromArray(dataArray, 14), // 报警状态
      reserve5: ByteUtil.parseInt16FromArray(dataArray, 15), // 保留
      reserve6: ByteUtil.parseInt16FromArray(dataArray, 16), // 保留
      equiNo: ByteUtil.parseUint32FromArray(dataArray, 17), // 设备序列号
      softVersion: ByteUtil.parseUint16FromArray(dataArray, 19), // 软件版本
      zdqs: ByteUtil.parseInt16FromArray(dataArray, 31), // 转圈数
      dqjdcgq: ByteUtil.parseInt16FromArray(dataArray, 33), // 单圈角度传感器(原始ADC)
    }
    // 计算实际值（带单位转换）
    const processedData = {
      ...deviceData,
      kdValue: (deviceData.kd * 0.1).toFixed(1), // 开度百分比
      jsylDLValue: deviceData.jsylDL * 0.001, // 进水压力电流值
      hsylDLValue: deviceData.hsylDL * 0.001, // 回水压力电流值
      jsylValue: (deviceData.jsyl * 0.001).toFixed(3), // 进水压力值
      hsylValue: (deviceData.hsyl * 0.001).toFixed(3), // 回水压力值
      jswdDZValue: deviceData.jswdDZ * 0.001, // 进水温度电阻值
      hswdDZValue: deviceData.hswdDZ * 0.001, // 回水温度电阻值
      jswdValue: (deviceData.jswd * 0.01).toFixed(2), // 进水温度值
      hswdValue: (deviceData.hswd * 0.01).toFixed(2), // 回水温度值
      motorCurrentValue: Math.round(deviceData.motorCurrent * 0.3846) // 电机电流值 (mA)，不显示小数点
    }
    return processedData
  }
})